#include<iostream>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include<unistd.h>
#include<string.h>
#include <arpa/inet.h>
using namespace std;

class UdpServer
{
  public:

    UdpServer(string ip,int port)
      :_sockfd(-1)
       ,_port(port)
       ,_ip(ip)
  {};

    bool InitServer()
    {
      //创建套接字
      _sockfd=socket(AF_INET,SOCK_DGRAM,0);
      if(_sockfd<0)
      {
        cerr<<"socket error"<<endl;
        return false;
      }
      cout<<"socket create success,sockfd: "<<_sockfd<<endl;

      //填充网络相关信息    
      struct sockaddr_in local;
      memset(&local,'\0',sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons(_port); //主机字节序转换成网络字节序
      local.sin_addr.s_addr = inet_addr(_ip.c_str());

      //绑定
      if(bind(_sockfd,(struct sockaddr*)&local,sizeof(sockaddr))<0)
      {
        cerr<<"bind fail"<<endl;
        return false;
      }
      cout<<"bind success"<<endl;
      return true;
    }

    void Start()
    {
#define SIZE 128
      char buf[SIZE];
      while(1)
      {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        ssize_t size = recvfrom(_sockfd,buf,sizeof(buf)-1,0,(struct sockaddr*)&peer,&len);
        if(size>0)
        {
          buf[size] = '\0';
          int port = ntohs(peer.sin_port);
          string ip = inet_ntoa(peer.sin_addr);
          cout<<ip<<":"<<port<<"#"<<buf<<endl;
        }
        else 
        {
          cout<<"recvfrom fail"<<endl;
        }
      }
    }

    ~UdpServer()
    {
      if(_sockfd>=0)
      {
        close(_sockfd);
      }
    }
  private:
    int _sockfd;//文件描述符
    int _port;//端口
    string _ip;//IP
};


int main(int argc,char* argv[])
{
  if(argc!=2)
  {
    cerr<<"Usage: "<<argv[0]<<" port"<<endl;
    return 1;
  }

  string ip="127.0.0.1";
  int port = atoi(argv[1]);
  UdpServer* svr = new UdpServer(ip,port);
  svr->InitServer();
  svr->Start();
  return 0;
}
